use bevy::prelude::*;
use rand::Rng;

use super::drops::monster_drops_exp;

///角色移动速度
static PLAYER_MOVE_SPEED: f32 = 120.;
///怪物移动速度
static MONSTER_MOVE_SPEED: f32 = 60.;
///怪物生成半径
static SPAWN_MONSTER_RADIUS: f32 = 600.;
///怪物生成速度
static SPAWN_MONSTER_TIME: f32 = 2.;
///怪物每波生成多少个
static SPAWN_MONSTER_COUNT: i16 = 5;
///行动单位渲染层级
static ACTOR_RENDERING_LEVEL: f32 = 10.;
///初始升级需要经验 max Exp
pub static INITIAL_UP_MXP_LEVEL_EXP: usize = 20;

#[derive(Component)]
pub struct HP(f32);

#[derive(Component)]
pub struct Player;

#[derive(Component)]
pub struct Monster;

///怪物被攻击动画计时器
#[derive(Resource)]
pub struct AttackMonstrtAminTime {
    main_timer: Timer,
}

///怪物生成计时器
#[derive(Resource)]
pub struct BuildMonstrtTime {
    main_timer: Timer,
}

///怪物生成计时器
#[derive(Resource)]
pub struct PlayerAttackTime {
    main_timer: Timer,
}

///游戏分数
#[derive(Resource)]
pub struct Scoreboard {
    pub score: usize,
}

///角色等级
#[derive(Resource)]
pub struct PlayerLevel {
    pub level: usize,
}

///角色经验
#[derive(Resource)]
pub struct PlayerExp {
    pub exp: usize,
}

///角色升级经验
#[derive(Resource)]
pub struct PlayerUpExp {
    pub exp: usize,
}

///创建角色
pub fn spawn_role(mut com: Commands, asset_server: Res<AssetServer>) {
    let player_pos = Vec3::new(0., 0., ACTOR_RENDERING_LEVEL);
    let player = (
        SpriteBundle {
            texture: asset_server.load("role/role.png"),
            transform: Transform {
                translation: player_pos,
                rotation: Quat::IDENTITY,
                scale: Vec3::ONE * 2.,
            },
            ..default()
        },
        Player,
    );
    com.spawn(player).insert(HP(10.));
}

///创建怪物
pub fn spawn_monster(
    mut com: Commands,
    asset_server: Res<AssetServer>,
    time: Res<Time>,
    mut build_monstrt_time: ResMut<BuildMonstrtTime>,
    palyer_q: Query<&mut Transform, (With<Player>, Without<Monster>)>,
) {
    //怪物生成计数器
    if build_monstrt_time
        .main_timer
        .tick(time.delta())
        .just_finished()
    {
        //每波生成10个怪物
        for _ in 0..SPAWN_MONSTER_COUNT {
            //在角色半径600r范围生成怪物
            let mut rng = rand::thread_rng();
            let palyer = palyer_q.get_single();
            let mut direction = Vec3::new(rng.gen_range(-1.0..=1.), rng.gen_range(-1.0..=1.), 0.)
                .normalize_or_zero()
                * SPAWN_MONSTER_RADIUS;
            direction.z = ACTOR_RENDERING_LEVEL;
            match palyer {
                Ok(pos) => direction += pos.translation,
                Err(_) => print!("没有找到playe"),
            }

            let monster = (
                SpriteBundle {
                    texture: asset_server.load("role/monster_tentackle.png"),
                    transform: Transform {
                        translation: direction,
                        rotation: Quat::IDENTITY,
                        scale: Vec3::ONE,
                    },
                    ..default()
                },
                Monster,
            );
            com.spawn(monster).insert(HP(10.));
        }
    }
}

///怪物移动
pub fn monster_move(
    time: Res<Time>,
    mut monster_q: Query<&mut Transform, With<Monster>>,
    palyer_q: Query<&mut Transform, (With<Player>, Without<Monster>)>,
) {
    let palyer_pos = palyer_q.single();
    for mut monstrt_transform in monster_q.iter_mut() {
        let direction = palyer_pos.translation - monstrt_transform.translation;
        let movement = direction.normalize_or_zero() * MONSTER_MOVE_SPEED * time.delta_seconds();
        monstrt_transform.translation += movement;
    }
}

///移动角色系统
pub fn move_player(
    key_input: ResMut<ButtonInput<KeyCode>>,
    time: Res<Time>,
    mut player_q: Query<&mut Transform, With<Player>>,
) {
    let mut player_transform = player_q.single_mut();
    let mut direction = Vec3::ZERO;
    //前进
    if key_input.pressed(KeyCode::KeyW) {
        direction += Vec3::Y;
    }

    //后退
    if key_input.pressed(KeyCode::KeyS) {
        direction -= Vec3::Y;
    }

    //左
    if key_input.pressed(KeyCode::KeyA) {
        direction -= Vec3::X;
    }

    //右
    if key_input.pressed(KeyCode::KeyD) {
        direction += Vec3::X;
    }

    let movement = direction.normalize_or_zero() * PLAYER_MOVE_SPEED * time.delta_seconds();
    player_transform.translation += movement;
}

///角色攻击怪物
pub fn palyer_atttack(
    time: Res<Time>,
    mut palyer_attack_time: ResMut<PlayerAttackTime>,
    mut attack_monstrt_admin_time: ResMut<AttackMonstrtAminTime>,
    mut monster_hp_q: Query<(&mut HP, &Transform, &mut Sprite), With<Monster>>,
    palyer_q: Query<&Transform, (With<Player>, Without<Monster>)>,
) {
    if palyer_attack_time
        .main_timer
        .tick(time.delta())
        .just_finished()
    {
        let palyer_pos = palyer_q.single();
        for (mut hp, monster_transform, mut sprite) in monster_hp_q.iter_mut() {
            let distance = ((palyer_pos.translation.x - monster_transform.translation.x).powi(2)
                + (palyer_pos.translation.y - monster_transform.translation.y).powi(2))
            .sqrt();
            if distance <= 150. {
                hp.0 -= 6.;
                sprite.color = Color::RED;
                attack_monstrt_admin_time.main_timer.reset();
            }
        }
    }
    if attack_monstrt_admin_time
        .main_timer
        .tick(time.delta())
        .finished()
    {
        for (_, _, mut sprite) in monster_hp_q.iter_mut() {
            sprite.color = Color::WHITE;
        }
    }
}

//怪物死亡
pub fn destroyed_monster(
    mut com: Commands,
    mut scoreboard: ResMut<Scoreboard>,
    mut monster_q: Query<(Entity, &Transform, &HP), With<Monster>>,
    asset_server: Res<AssetServer>,
) {
    for (entity, transform, hp) in monster_q.iter_mut() {
        if hp.0 <= 0.0 {
            let mut rng = rand::thread_rng();
            if rng.gen_range(0.0..=1.) >= 0.4 {
                com.spawn(monster_drops_exp(
                    transform.translation,
                    asset_server.load("prop/explosion.png").clone(),
                ));
            }
            com.entity(entity).despawn();
            scoreboard.score += 1;
        }
    }
}

pub fn player_level_up(
    mut palyer_level: ResMut<PlayerLevel>,
    mut palyer_exp: ResMut<PlayerExp>,
    mut paleyr_up_exp: ResMut<PlayerUpExp>,
) {
    if palyer_exp.exp >= paleyr_up_exp.exp {
        palyer_level.level += 1;
        palyer_exp.exp -= paleyr_up_exp.exp;
        paleyr_up_exp.exp += INITIAL_UP_MXP_LEVEL_EXP;
    }
}

impl BuildMonstrtTime {
    pub fn new() -> Self {
        Self {
            main_timer: Timer::from_seconds(SPAWN_MONSTER_TIME, TimerMode::Repeating),
        }
    }
}

impl Default for BuildMonstrtTime {
    fn default() -> Self {
        Self::new()
    }
}

impl PlayerAttackTime {
    pub fn new() -> Self {
        Self {
            main_timer: Timer::from_seconds(2., TimerMode::Repeating),
        }
    }
}

impl Default for PlayerAttackTime {
    fn default() -> Self {
        Self::new()
    }
}

impl AttackMonstrtAminTime {
    pub fn new() -> Self {
        Self {
            main_timer: Timer::from_seconds(0.1, TimerMode::Once),
        }
    }
}

impl Default for AttackMonstrtAminTime {
    fn default() -> Self {
        Self::new()
    }
}
